package alibaba.client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import alibaba.shared.AlibabaException;

public class AlibabaClientCLI {
	private static HelpFormatter formatter = new HelpFormatter();
	private static CommandLineParser parser = new GnuParser();

	@SuppressWarnings("serial")
	private static Map<String, Action> optionsMap = new HashMap<String, Action>() {
		{
			put("backupfile", Action.BACKUP_FILE);
			put("bf", Action.BACKUP_FILE);
			put("restorefile", Action.RESTORE_FILE);
			put("rf", Action.RESTORE_FILE);
			put("backupdir", Action.BACKUP_DIR);
			put("bd", Action.BACKUP_DIR);
			put("restoredir", Action.RESTORE_DIR);
			put("rd", Action.RESTORE_DIR);
			put("list", Action.LIST);
			put("ls", Action.LIST);
			put("check", Action.CHECK);
			put("ch", Action.CHECK);
			put("help", Action.HELP);
			put("?", Action.HELP);
		}
	};

	private enum Action {
		BACKUP_DIR, BACKUP_FILE, HELP, ERROR, RESTORE_FILE, RESTORE_DIR, LIST, CHECK;
	}

	protected static void printMainHelp() {
		System.out.println("Usage: alibaba command [options]");
		System.out.println("Commands:\n");
		System.out.println("Command name\t\tShort name\tDescription");
		System.out.println("--------------------------------------------------------------");
		System.out.println("backupfile\t\tbf\t\tBackup a file");
		System.out.println("restorefile\t\trf\t\tRestore a file");
		System.out.println("backupdir\t\tbd\t\tBackup a directory");
		System.out.println("restoredir\t\trd\t\tRestore a directory");
		System.out.println("list\t\t\tls\t\tList files in a directory");
		System.out.println("check\t\t\tch\t\tCheck and validate backup files");
		System.out.println("help\t\t\t?\t\tPrint usage information");
	}

	protected static void checkFilesCmd(String[] args) throws AlibabaException, URISyntaxException {
		CommandLine commandLine = parseCmd("The name of the client directory to "
				+ "check the files from", "directory_name", "dir", "check", args);
		if (commandLine != null) {
			String directoryName = commandLine.getOptionValue("dir");
			String user = commandLine.getOptionValue("user");
			AlibabaClient.checkFilesCmd(directoryName, user);
		}
	}

	protected static void listFilesCmd(String[] args) throws AlibabaException, URISyntaxException {
		CommandLine commandLine = parseCmd("The name of the client directory to "
				+ "list the files from", "directory_name", "dir", "list", args);
		if (commandLine != null) {
			String directoryName = commandLine.getOptionValue("dir");
			String user = commandLine.getOptionValue("user");
			AlibabaClient.listFilesCmd(directoryName, user);
		}
	}

	protected static void backupDirCmd(String[] args) throws AlibabaException, URISyntaxException {
		CommandLine commandLine = parseCmd("The name of the client directory", "directory_name",
				"dir", "backupdir", args);
		if (commandLine != null) {
			String directoryName = commandLine.getOptionValue("dir");
			String user = commandLine.getOptionValue("user");
			AlibabaClient.backupDir(directoryName, user);
		}
	}

	protected static void backupFileCmd(String[] args) throws AlibabaException, URISyntaxException {
		CommandLine commandLine = parseCmd("The file containing the data that will "
				+ "be sent to the remote server", "file_name", "file", "backupfie", args);
		if (commandLine != null) {
			String fileName = commandLine.getOptionValue("file");
			String user = commandLine.getOptionValue("user");
			AlibabaClient.backupFile(fileName, user);
		}
	}

	protected static void restoreDirCmd(String[] args) throws AlibabaException, URISyntaxException {
		CommandLine commandLine = parseCmd("The name of the client directory", "directory_name",
				"dir", "restoredir", args);
		if (commandLine != null) {
			String directoryName = commandLine.getOptionValue("dir");
			String user = commandLine.getOptionValue("user");
			AlibabaClient.restoreDir(directoryName, user);
		}
	}

	protected static void restoreFileCmd(String[] args) throws AlibabaException, URISyntaxException {
		CommandLine commandLine = parseCmd("The file containing the data that will "
				+ "be sent to the remote server", "file_name", "file", "restorefile", args);
		if (commandLine != null) {
			String fileName = commandLine.getOptionValue("file");
			String user = commandLine.getOptionValue("user");
			AlibabaClient.restoreFile(fileName, user);
		}
	}

	private static CommandLine parseCmd(String description, String argName, String optionName,
			String cmd, String[] args) {
		Options commandOptions = new Options();
		CommandLine commandLine = null;

		OptionBuilder.withDescription(description);
		OptionBuilder.hasArg();
		OptionBuilder.withArgName(argName);
		OptionBuilder.isRequired();
		commandOptions.addOption(OptionBuilder.create(optionName));

		OptionBuilder.withDescription("The user performing the operation");
		OptionBuilder.hasArg();
		OptionBuilder.withArgName("user_name");
		OptionBuilder.isRequired();
		commandOptions.addOption(OptionBuilder.create("user"));

		try {
			commandLine = parser.parse(commandOptions, args);
		} catch (ParseException exp) {
			System.out.println(exp.getMessage());
			formatter.printHelp(cmd, commandOptions);
		}

		return commandLine;
	}

	private static void doCommand(String[] args) throws Exception {
		String commandString = args[0];
		Action action = optionsMap.get(commandString);
		if (action == null) {
			System.out.println("Input error. Type 'help' for usage");
			return;
		}

		String[] cmdArgs = new String[args.length - 1];
		System.arraycopy(args, 1, cmdArgs, 0, args.length - 1);

		switch (action) {
		case BACKUP_FILE:
			backupFileCmd(cmdArgs);
			break;

		case RESTORE_FILE:
			restoreFileCmd(args);
			break;

		case BACKUP_DIR:
			backupDirCmd(cmdArgs);
			break;

		case RESTORE_DIR:
			restoreDirCmd(args);
			break;

		case LIST:
			listFilesCmd(args);
			break;

		case CHECK:
			checkFilesCmd(args);
			break;

		case HELP:
			printMainHelp();
			break;

		default:
			System.out.println("Not implememented yet.");
		}
	}

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		if (args.length == 0) {
			System.out.println("Type 'alibaba help' for usage");
			System.exit(-1);
		}
		try {
			doCommand(args);
		} catch (MalformedURLException e) {
			e.printStackTrace();
			System.out
					.println("An exception occurred while processing the command. The results are inpredictable.");
		} catch (IOException e) {
			e.printStackTrace();
			System.out
					.println("An exception occurred while processing the command. The results are inpredictable.");
		}
	}
}
